//
// Created by mio on 25-5-23.
//

#ifndef DXGICAPTURE_H
#define DXGICAPTURE_H


#include <QThread>
#include <QDebug>
#include <memory>
#include <mutex>
#include <atomic>
#include <chrono>
#include <d3d11.h>
#include <dxgi1_2.h>

#include "VideoCapture.h"

using FrameContainer = std::vector<quint8>;

// 包含你项目中的 AV_Common.h 以使用 AVFramePtr 等定义
#include "AV_Common.h" // 假设路径正确

class DXGICapture : public VideoCapture
{
    Q_OBJECT // 如果需要在信号槽中使用

public:
    DXGICapture();
    DXGICapture(const DXGICapture&) = delete;
    DXGICapture& operator=(const DXGICapture&) = delete;
    virtual ~DXGICapture();

public:
    // display_index: 要捕获的显示器索引 (通常0是主显示器)
    // capture_rect_*: 指定捕获区域，如果 width/height 为0，则捕获整个显示器
    bool Init(qint32 display_index = 0, const QRect& capture_region = QRect()) override;
    bool Close() override;

    // 捕获一帧，输出为 AV_PIX_FMT_BGRA 格式的 AVFrame
    // 返回true表示成功捕获到新的一帧，false表示失败或无新帧
    bool CaptureFrame(AVFramePtr& bgra_frame) override;

protected:
    virtual void run() override;

private:
    void Cleanup();    // 内部资源清理函数
    bool InitializeDXGI(qint32 display_index, RECT target_capture_rect);
    bool GetDisplayRect(qint32 display_index, RECT& display_rect);


    std::mutex          mutex_; // 用于保护对捕获数据的访问（如果run和CaptureFrame在不同线程）
                               // 但按照GDICapture设计，CaptureFrame应从run线程准备好的数据中取

    // DXGI 相关成员
    ID3D11Device* d3d_device_;
    ID3D11DeviceContext* d3d_context_;
    IDXGIOutputDuplication* desk_dupl_;
    ID3D11Texture2D* staging_texture_; // 用于从GPU复制数据到CPU可读内存的临时纹理
    D3D11_TEXTURE2D_DESC    texture_desc_;    // 捕获到的纹理的描述

    RECT                capture_rect_;      // 实际捕获的桌面区域
    bool                capture_full_screen_;


    // 帧率控制和FPS统计 (与GDICapture类似)
    AVFramePtr          captured_bgra_frame_; // 存储最近捕获的BGRA帧
    std::mutex          frame_mutex_;         // 保护 captured_bgra_frame_
};




#endif //DXGICAPTURE_H
